﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ColorClusteringSOM.Evaluation
{
    class XieBeni
    {
        private List<NeuronRough> leaders = null;

        public XieBeni(List<NeuronRough> leaders)
        {
            this.leaders = leaders;
        }



        public double XieBeniIndex()
        {
            double sigma = 0.0; // sigma
            double uliNA2 = 0.0;
            double[] leaderWeigh = null;          
            double yes = 1;     // patri do dolni aproximace
            double maybe = 0.5; // patri do horni aproximace
            int allneuronsCount = 0;
            int clusterNumber = -1;

            foreach (NeuronRough cluster in leaders)
            {
                clusterNumber++;
                leaderWeigh = cluster.LeaderWeight; // vahy leadra nebo-centra shluku
                allneuronsCount += cluster.LowerAppNeuronsArray.Count + cluster.UpperAppNeuronsArray.Count; //pocet vsech neuronu v klastru se 
               // pricte do celkoveho poctu pridani do celkove
                uliNA2 = yes * yes;     //Uli^2 pro dolni app

                foreach (NeuronRough neuron in cluster.LowerAppNeuronsArray)
                {
                    sigma += (uliNA2 * euklidNA2(leaderWeigh, neuron.Neuron.Weights));
                }
                uliNA2 = maybe*maybe;     //Uli^2  pro horni app
                foreach (NeuronRough neuron in cluster.UpperAppNeuronsArray)
                {
                    sigma += (uliNA2 * euklidNA2(leaderWeigh, neuron.Neuron.Weights));
                }
            }

            double Fi = sigma / allneuronsCount; // tedka mame Fi
            double S = Separation();

            return (Fi / S);
        }


        private double Separation() 
        {
            double minimalDistance = Double.MaxValue;
            NeuronRough pomClus = null;
            bool firstIter = true;

            foreach (NeuronRough cluster in leaders) //hledani nejmensi vzdalenosti center
            {
                if (firstIter)
                {
                    pomClus = cluster;  //inicializace prvniho shluku
                    firstIter = false;   
                    continue;
                }

                double pomDistance = euklidNA2(pomClus.LeaderWeight, cluster.LeaderWeight);
                if (pomDistance == 0)
                {
                    continue;
                }
                if (pomDistance < minimalDistance)
                {
                    minimalDistance = pomDistance;
                }
            }
            return minimalDistance;
        }

        private double euklidNA2(double[] input, double[] input2)
        {

            double euDistance = 0;
            double pom = 0;

            for (int i = 0; i < input.Length; i++)
            {
                pom = input[i] - input2[i];
                euDistance += pom * pom;
            }

            return euDistance;
        }
    }
}
